package com.ketayao.fensy.webutil;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import com.ketayao.fensy.cache.CacheManager;
import com.ketayao.fensy.mvc.WebContext;
import com.ketayao.fensy.util.RandomStringUtils;
import com.ketayao.fensy.util.StringUtils;

/**
 * //调用方法
 * if(!ImageCaptchaService.validate(ctx.request()))
 * //提示错误信息
 * 图形验证码
 */
public class ImageCaptchaService {

    private final static String CACHE_REGION = "session";
    private final static String COOKIE_NAME  = "_reg_key_";
    private static int          WIDTH        = 120;
    private static int          HEIGHT       = 40;
    private static int          LENGTH       = 5;
    private final static Random random       = new Random();

    /**
     * 生成验证码
     * @param req
     * @param res
     * @throws IOException 
     */
    public static void get(WebContext ctx) throws IOException {
        if (ctx.isRobot()) {
            ctx.forbidden();
            return;
        }
        ctx.closeCache();
        ctx.getResponse().setContentType("image/png");
        _render(_generateRegKey(ctx), ctx.getResponse().getOutputStream(), WIDTH, HEIGHT);
    }

    /**
     * 检查验证码是否正确
     * @param req
     * @return
     */
    public static boolean validate(HttpServletRequest req) {
        Cookie cke = RequestUtils.getCookie(req, COOKIE_NAME);
        if (cke == null) {
            String ssnId = req.getSession().getId();
            String code1 = CacheManager.get(String.class, CACHE_REGION, ssnId);
            String code2 = req.getParameter("verifyCode");
            return StringUtils.endsWithIgnoreCase(code1, code2);
        }
        if (cke != null && StringUtils.isNotBlank(cke.getValue())) {
            String key = cke.getValue();
            String code1 = CacheManager.get(String.class, CACHE_REGION, key);
            String code2 = req.getParameter("verifyCode");
            return StringUtils.endsWithIgnoreCase(code1, code2);
        }
        return false;
    }

    private static String _generateRegKey(WebContext ctx) {
        Cookie cke = ctx.getCookie(COOKIE_NAME);
        String REG_VALUE = null;
        if (cke == null || StringUtils.isBlank(cke.getValue())) {
            REG_VALUE = RandomStringUtils.randomAlphanumeric(20);
            ctx.setCookie(COOKIE_NAME, REG_VALUE, 3600, true);
        } else
            REG_VALUE = cke.getValue();
        String code = RandomStringUtils.randomAlphanumeric(LENGTH).toUpperCase();
        code.replace('0', 'W');
        code.replace('o', 'R');
        code.replace('I', 'E');
        code.replace('1', 'T');
        CacheManager.put(CACHE_REGION, REG_VALUE, code);
        if (ctx.getSession() != null) {
            CacheManager.put(CACHE_REGION, ctx.getSession().getId(), code);
        }
        return code;
    }

    /**
     * 画随机码图
     * @param text
     * @param out
     * @param width
     * @param height
     * @throws IOException
     */
    private static void _render(String text, OutputStream out, int width,
                                int height) throws IOException {
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D) bi.getGraphics();

        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);
        //g.setColor(Color.RED);
        //g.drawRect(1,1,width-2,height-2);
        for (int i = 0; i < 10; i++) {
            g.setColor(_getRandColor(150, 250));
            g.drawOval(random.nextInt(110), random.nextInt(24), 5 + random.nextInt(10),
                5 + random.nextInt(10));
        }
        Font mFont = new Font("Arial", Font.ITALIC, 28);
        g.setFont(mFont);
        g.setColor(_getRandColor(10, 240));
        g.drawString(text, 10, 30);
        ImageIO.write(bi, "png", out);
    }

    private static Color _getRandColor(int fc, int bc) {//给定范围获得随机颜色
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    public static void main(String[] args) throws IOException {
        String code = RandomStringUtils.randomAlphanumeric(LENGTH).toUpperCase();
        code = code.replace('0', 'W');
        code = code.replace('o', 'R');
        code = code.replace('I', 'E');
        code = code.replace('1', 'T');

        FileOutputStream out = new FileOutputStream("d:\\aa.jpg");
        _render(code, out, 120, 40);
    }

}
